package com.xinruke.hostels.reservation.user.service;

import com.xinruke.hostels.common.cache.ReservationUserCache;
import com.xinruke.hostels.common.cache.vo.LoginReservationResultVO;
import com.xinruke.hostels.common.constants.LoginConstants;
import com.xinruke.hostels.common.constants.RedisConstants;
import com.xinruke.hostels.common.mybatis.MyExample;
import com.xinruke.hostels.common.po.MhHuiyuan;
import com.xinruke.hostels.common.po.YewuyonghuCaozuoRizhi;
import com.xinruke.hostels.common.service.MemberOperateLogService;
import com.xinruke.hostels.common.util.CustomSecurity;
import com.xinruke.hostels.common.util.JwtUtil;
import com.xinruke.hostels.common.vo.ResultVO;
import com.xinruke.hostels.common.vo.query.EConditionOperator;
import com.xinruke.hostels.common.vo.query.QueryConditions;
import com.xinruke.hostels.reservation.user.interfaces.dto.*;
import com.xinruke.hostels.reservation.user.mapper.MhHuiyuanMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName LoginService
 * @CreateDate 2019/6/15
 * @Author FengXinQiang
 * @Version V1.0.0.0
 * @Decription 登录Service
 */
@Service
@Slf4j
public class LoginService {
    @Autowired
    MhHuiyuanMapper huiyuanMapper;

    @Resource(name = "commonRedisTemplate")
    RedisTemplate commonRedisTemplate;

    @Value("${login.max-valid-second}")
    private long loginMaxValidSecond;

    @Autowired
    ReservationUserCache reservationUserCache;

    @Autowired
    MemberOperateLogService memberOperateLogService;

    /**
     * 登录
     *
     * @param loginDTO
     * @return
     */
    public ResultVO<LoginResultDTO> userLogin(LoginDTO loginDTO) {
        ResultVO<LoginResultDTO> resultVO = ResultVO.fail();

        String loginCode = loginDTO.getLoginCode();
        loginCode = CustomSecurity.encodeIDCard(loginCode);

        //根据登录账号，获取用户信息
        QueryConditions queryConditions = new QueryConditions();
        queryConditions.addCondition("shenfenzhenghao", EConditionOperator.EQULS, loginCode);
        queryConditions.addCondition("shanchubiaoshi", EConditionOperator.EQULS, 0);
        MyExample myExample = new MyExample(MhHuiyuan.class, queryConditions);
        List<MhHuiyuan> huiyuanList = huiyuanMapper.selectByExample(myExample);
        if (CollectionUtils.isEmpty(huiyuanList) || huiyuanList.size() != 1) {
            resultVO.setMessage("用户不存在或密码错误");
            return resultVO;
        }

        //验证用户登录信息，对密码做加密处理后验证是否正确
        MhHuiyuan huiyuan = huiyuanList.get(0);
        String password = loginDTO.getLoginPassword();
        password = CustomSecurity.createUserPassword(huiyuan.getShenfenzhenghao(), huiyuan.getYan(), password);
        if (!password.equals(huiyuan.getMima())) {
            resultVO.setMessage("用户不存在或密码错误");
            return resultVO;
        }

        //将登录信息放入缓存
        if (loginMaxValidSecond <= 0) {
            loginMaxValidSecond = 60 * 20;
        }
        String token = JwtUtil.createReservationToken(loginCode, null);
        LoginReservationResultVO loginReservationResultVO = new LoginReservationResultVO();
        BeanUtils.copyProperties(huiyuan, loginReservationResultVO);
        loginReservationResultVO.setToken(token);
        commonRedisTemplate.opsForValue().set(RedisConstants.RESERVATION_LOGIN_TOKEN_KEY_PREFIX + loginCode, loginReservationResultVO, loginMaxValidSecond, TimeUnit.SECONDS);
        log.info("将登录信息放入缓存" + RedisConstants.RESERVATION_LOGIN_TOKEN_KEY_PREFIX + loginCode + loginMaxValidSecond + TimeUnit.SECONDS);

        //写入操作日志
        YewuyonghuCaozuoRizhi yewuyonghuCaozuoRizhi = new YewuyonghuCaozuoRizhi(YewuyonghuCaozuoRizhi.YEWUYONGHUCAOZUORIZHI_CAOZUO_DENGLU, "预订系统登录", "登录成功");
        yewuyonghuCaozuoRizhi.setYewuyonghuId(huiyuan.getId());
        yewuyonghuCaozuoRizhi.setYewuyonghumingcheng(huiyuan.getXingming());
        memberOperateLogService.writeOperateLog(yewuyonghuCaozuoRizhi);

        //返回登录信息
        LoginResultDTO loginResultDTO = new LoginResultDTO();
        BeanUtils.copyProperties(loginReservationResultVO, loginResultDTO);
        String loginShenfenzhenghao = CustomSecurity.hideIDCard(loginResultDTO.getShenfenzhenghao());
        String loginMobile = CustomSecurity.decodeMobile(loginResultDTO.getShoujihao());
        loginResultDTO.setShenfenzhenghao(loginShenfenzhenghao);
        loginResultDTO.setShoujihao(loginMobile);

        resultVO.setCode(ResultVO.SUCCESS);
        resultVO.setMessage("登录成功");
        resultVO.setData(loginResultDTO);
        return resultVO;
    }

    /**
     * 登录验证
     *
     * @param loginValidateDTO
     * @return
     */
    public ResultVO<LoginReservationValidateResultDTO> loginValidate(LoginReservationValidateDTO loginValidateDTO) {
        ResultVO<LoginReservationValidateResultDTO> resultVO = ResultVO.fail();
        LoginReservationValidateResultDTO loginValidateResultDTO = new LoginReservationValidateResultDTO();

        String token = loginValidateDTO.getToken();
        String loginCode = JwtUtil.getLoginCode(token);

        //从缓存中获取登录信息并验证
        LoginReservationResultVO loginResultVO = (LoginReservationResultVO) commonRedisTemplate.opsForValue().get(RedisConstants.RESERVATION_LOGIN_TOKEN_KEY_PREFIX + loginCode);
        if (loginResultVO != null) {
            String loginToken = loginResultVO.getToken();
            if (token.equals(loginToken)) {
                if (loginMaxValidSecond <= 0) {
                    loginMaxValidSecond = 60 * 20;
                }
                //重新设置token的过期时间
                commonRedisTemplate.expire(RedisConstants.RESERVATION_LOGIN_TOKEN_KEY_PREFIX + loginCode, loginMaxValidSecond, TimeUnit.SECONDS);

                loginValidateResultDTO.setLoginCode(CustomSecurity.hideIDCard(loginCode));
                resultVO.setCode(ResultVO.SUCCESS);
                resultVO.setMessage("登录验证通过");
                resultVO.setData(loginValidateResultDTO);
            }
        }

        return resultVO;
    }

    /**
     * 获取登录用户信息
     *
     * @param loginUserInfoQueryDTO
     * @return
     */
    public ResultVO<LoginUserInfoQueryResultDTO> getLoginUserInfo(LoginUserInfoQueryDTO loginUserInfoQueryDTO) {
        ResultVO<LoginUserInfoQueryResultDTO> resultVO = ResultVO.fail();
        LoginUserInfoQueryResultDTO loginUserInfoQueryResultDTO = new LoginUserInfoQueryResultDTO();

        //从缓存中获取登录信息
        LoginReservationResultVO loginReservationResultVO = reservationUserCache.getLoginReservationUserInfo();
        BeanUtils.copyProperties(loginReservationResultVO, loginUserInfoQueryResultDTO);

        String loginShenfenzhenghao = CustomSecurity.hideIDCard(loginReservationResultVO.getShenfenzhenghao());
        String loginMobile = CustomSecurity.hideMobile(loginReservationResultVO.getShoujihao());
        loginUserInfoQueryResultDTO.setShenfenzhenghao(loginShenfenzhenghao);
        loginUserInfoQueryResultDTO.setShoujihao(loginMobile);

        resultVO = ResultVO.success();
        resultVO.setData(loginUserInfoQueryResultDTO);

        return resultVO;
    }

    /**
     * 退出当前登录用户
     *
     * @return
     */
    public ResultVO userLoginOut() {
        ResultVO resultVO = ResultVO.fail();

        String loginCode = "";
        try {
            LoginReservationResultVO loginReservationResultVO = reservationUserCache.getLoginReservationUserInfo();
            loginCode = loginReservationResultVO.getShenfenzhenghao();

            //写入操作日志
            YewuyonghuCaozuoRizhi yewuyonghuCaozuoRizhi = new YewuyonghuCaozuoRizhi(YewuyonghuCaozuoRizhi.YEWUYONGHUCAOZUORIZHI_CAOZUO_DENGLU, "预订系统退出", "退出成功");
            yewuyonghuCaozuoRizhi.setYewuyonghuId(loginReservationResultVO.getId());
            yewuyonghuCaozuoRizhi.setYewuyonghumingcheng(loginReservationResultVO.getXingming());
            memberOperateLogService.writeOperateLog(yewuyonghuCaozuoRizhi);
        } catch (Exception e) {
        }

        if (StringUtils.isEmpty(loginCode)) {
            try {
                HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
                String token = request.getHeader(LoginConstants.HEADER_TOKEN_NAME);
                loginCode = JwtUtil.getLoginCode(token);
            } catch (Exception e) {
            }
        }

        commonRedisTemplate.delete(RedisConstants.RESERVATION_LOGIN_TOKEN_KEY_PREFIX + loginCode);

        resultVO = ResultVO.success();

        return resultVO;
    }

}
